#!/usr/bin/perl
use strict;
use Getopt::Long;
use JNPR::Utils;

my $g_sql_out = [];
my $opts = {};
GetOptions ($opts, 'db=s');
if (!exists $opts->{'db'}) {
    die "Error: $0: Need --db <dbfile path>\n";
}
my $db = $opts->{'db'};

JNPR::Utils::mk_tables($db);




my $v;
if (scalar @ARGV) {
    svnlog2db_specific_versions();
    exit;
}
else {
    svnlog2db_remaining_versions();
}


#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub svnlog2db_specific_versions
{
    if ($ARGV[0] eq '-') {
        while (my $v = <STDIN>) {
            chomp $v;
            print ">> $v\n";
            svnlog2db($v);
            print "<< $v\n";
        }
    }
    else {
        for my $v (@ARGV) {
            svnlog2db($v);
        }
    }
    flush_to_nodes_table();
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub svnlog2db_remaining_versions
{

    my ($nodes_hi_rev, $nodes_lo_rev) = JNPR::Utils::get_counts($db, 'nodes_hi_rev', 'nodes_lo_rev');
    if ($nodes_hi_rev == -1 and $nodes_lo_rev == -1) {
        my ($svn_hi_rev, $svn_lo_rev) = JNPR::Utils::get_counts($db, 'svn_hi_rev', 'svn_lo_rev');
        my ($done_lo, $done_hi) = (-1, -1);
        my $v = $svn_lo_rev;
        while (1) {
            my ($d) = "00$v" =~ /(..)$/;
            last if (!-e "$d/${v}-rlog.txt");
            print STDERR "$v\n";
            svnlog2db($v);
            if ($done_lo == -1 or $v < $done_lo) {
                $done_lo = $v;
            }
            if ($done_hi == -1 or $done_hi < $v) {
                $done_hi = $v;
            }
            if (-e 'kill') {
                unlink 'kill';
                flush_to_nodes_table();
                JNPR::Utils::set_counts($db, 'nodes_hi_rev', $done_hi);
                JNPR::Utils::set_counts($db, 'nodes_lo_rev', $done_lo);
                exit;
            }
            $v++;
        }
        flush_to_nodes_table();
        JNPR::Utils::set_counts($db, 'nodes_hi_rev', $done_hi);
        JNPR::Utils::set_counts($db, 'nodes_lo_rev', $done_lo);
    }
    else {
        # Downward
        {
            my $v = $nodes_lo_rev - 1;
            my $done_lo = $nodes_lo_rev;
            while (1) {
                my ($d) = "00$v" =~ /(..)$/;
                last if (!-e "$d/${v}-rlog.txt");
                print STDERR "$v\n";
                svnlog2db($v);
                $done_lo = $v;
                if (-e 'kill') {
                    unlink 'kill';
                    flush_to_nodes_table();
                    JNPR::Utils::set_counts($db, 'nodes_lo_rev', $done_lo);
                    exit;
                }
                $v--;
            }
            flush_to_nodes_table();
            JNPR::Utils::set_counts($db, 'nodes_lo_rev', $done_lo);
        }
        # Upward
        {
            my $v = $nodes_hi_rev + 1;
            my $done_hi = $nodes_hi_rev;
            while (1) {
                my ($d) = "00$v" =~ /(..)$/;
                last if (!-e "$d/${v}-rlog.txt");
                print STDERR "$v\n";
                svnlog2db($v);
                $done_hi = $v;
                if (-e 'kill') {
                    unlink 'kill';
                    flush_to_nodes_table();
                    JNPR::Utils::set_counts($db, 'nodes_hi_rev', $done_hi);
                    exit;
                }
                $v++;
            }
            flush_to_nodes_table();
            JNPR::Utils::set_counts($db, 'nodes_hi_rev', $done_hi);
        }
    }
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub svnlog2db
{
    my $v  = shift;
    my ($d) = "00$v" =~ /(..)$/;
    my $rlogfile = "$d/${v}-rlog.txt";
    unless (open F, "<$rlogfile") {
        print "Not found: $rlogfile\n";
        next;
    }
    my @rlog = <F>;
    close F;

    my $node_detail = JNPR::Utils::grok_rlog(\@rlog);
    # Returns reference to this hash
    #   {
    #       rev
    #       author
    #       date
    #       branch
    #       parent_branch
    #       parent_rev
    #       dead_branch
    #       merged
    #   }
    to_nodes($node_detail);
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub to_nodes
{
    my ($node_detail) = shift;

    return if ($node_detail->{rev} eq '');
    push_to_nodes_table(
                      $node_detail->{rev},
                      $node_detail->{author},
                      $node_detail->{date},
                      $node_detail->{branch},
                      $node_detail->{dead_branch},
                    );
}


#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
{
my $n;
my $cmd;
sub push_to_nodes_table
{
    my ($rev, $author, $date, $branch, $dead_branch) = @_;
    $cmd .= "INSERT INTO nodes ( rev, author, date, branch, dead_branch ) VALUES ( $rev, \"$author\", \"$date\", \"$branch\", \"$dead_branch\" );\n";
    $n++;
    if ($n == 5000) {
        flush_to_nodes_table();
    }
}

sub flush_to_nodes_table
{
    $cmd = "BEGIN TRANSACTION;\n" . $cmd . "COMMIT;\n";
    JNPR::Utils::sql_query($db, \$cmd, $g_sql_out);
    $n = 0;
    $cmd = '';
}

}

